<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>Introduction - Rauthy Documentation</title>


        <!-- Custom HTML head -->

        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff">

        <link rel="icon" href="favicon.svg">
        <link rel="shortcut icon" href="favicon.png">
        <link rel="stylesheet" href="css/variables.css">
        <link rel="stylesheet" href="css/general.css">
        <link rel="stylesheet" href="css/chrome.css">
        <link rel="stylesheet" href="css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="fonts/fonts.css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" id="highlight-css" href="highlight.css">
        <link rel="stylesheet" id="tomorrow-night-css" href="tomorrow-night.css">
        <link rel="stylesheet" id="ayu-highlight-css" href="ayu-highlight.css">

        <!-- Custom theme stylesheets -->
        <link rel="stylesheet" href="./mdbook-admonish.css">


        <!-- Provide site root and default themes to javascript -->
        <script>
            const path_to_root = "";
            const default_light_theme = "light";
            const default_dark_theme = "navy";
        </script>
        <!-- Start loading toc.js asap -->
        <script src="toc.js"></script>
    </head>
    <body>
    <div id="mdbook-help-container">
        <div id="mdbook-help-popup">
            <h2 class="mdbook-help-title">Keyboard shortcuts</h2>
            <div>
                <p>Press <kbd>←</kbd> or <kbd>→</kbd> to navigate between chapters</p>
                <p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
                <p>Press <kbd>?</kbd> to show this help</p>
                <p>Press <kbd>Esc</kbd> to hide this help</p>
            </div>
        </div>
    </div>
    <div id="body-container">
        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script>
            try {
                let theme = localStorage.getItem('mdbook-theme');
                let sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script>
            const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
            let theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            const html = document.documentElement;
            html.classList.remove('light')
            html.classList.add(theme);
            html.classList.add("js");
        </script>

        <input type="checkbox" id="sidebar-toggle-anchor" class="hidden">

        <!-- Hide / unhide sidebar before it is displayed -->
        <script>
            let sidebar = null;
            const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            } else {
                sidebar = 'hidden';
            }
            sidebar_toggle.checked = sidebar === 'visible';
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <!-- populated by js -->
            <mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
            <noscript>
                <iframe class="sidebar-iframe-outer" src="toc.html"></iframe>
            </noscript>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle">
                <div class="sidebar-resize-indicator"></div>
            </div>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky">
                    <div class="left-buttons">
                        <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </label>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">Rauthy Documentation</h1>

                    <div class="right-buttons">
                        <a href="print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>

                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script>
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <p><img src="./rauthy_grey_small.png" alt="Rauthy Logo" /></p>
<h1 id="rauthy"><a class="header" href="#rauthy">Rauthy</a></h1>
<p>Rauthy - OpenID Connect Single Sign-On Identity &amp; Access Management</p>
<h2 id="what-it-is"><a class="header" href="#what-it-is">What it is</a></h2>
<p>Rauthy is a lightweight and easy to use OpenID Connect Identity Provider. It aims to be simple to both set up and
operate, with very secure defaults and lots of config options, if you need the flexibility. It puts heavy emphasis on
Passkeys and a very strong security in general. The project is written in Rust to be as memory efficient, secure and
fast as possible, and it can run on basically any hardware. If you need Single Sign-On support for IoT or headless
CLI tools, it's got you covered as well.<br />
You get High-Availability, client branding, UI translation, a nice Admin UI, Events and Auditing, and many more
features. By default, it runs on top of <a href="https://github.com/sebadob/hiqlite">Hiqlite</a> and does not depend on an external
database (Postgres as an alternative) to make it even simpler to operate, while scaling up to millions of users easily.</p>
<h3 id="secure-by-default"><a class="header" href="#secure-by-default">Secure by default</a></h3>
<p>It tries to be as secure as possible by default while still providing all the options needed to be compatible with
older systems. For instance, if you create a new OIDC client, it activates <code>ed25519</code> as the default algorithm for
token signing and S256 PKCE flow. This will not work with clients, which do not support it, but you can of course
deactivate this to your liking.</p>
<h3 id="mfa-and-passwordless-login"><a class="header" href="#mfa-and-passwordless-login">MFA and Passwordless Login</a></h3>
<p><strong>Option 1:</strong><br />
Password + Security Key (without User Verification):<br />
Rauthy provides FIDO 2 / Webauthn login flows. If you once logged in on a new client with your username + password,
you will get an encrypted cookie which will allow you to log in without a password from that moment on. You only need to
have a FIDO compliant Passkey being registered for your account.</p>
<p><strong>Option 2:</strong><br />
Passkey-Only Accounts:<br />
Rauthy supports Passkey-Only-Accounts: you basically just provide your E-Mail address and log in with
your FIDO 2 Passkey. Your account will not even have / need a password. This login flow is restricted though to only
those passkeys, that can provide User Verification (UV) to always have at least 2FA security.</p>
<blockquote>
<p>Discoverable credentials are discouraged with Rauthy (for good reason). This means you will need to enter your E-Mail
for the login (which will be autofilled after the first one), but Rauthy passkeys do not use any storage on your
device. For instance when you have a Yubikey which can store 25 passkeys, it will not use a single slot there even
having full support.</p>
</blockquote>
<h3 id="fast-and-efficient"><a class="header" href="#fast-and-efficient">Fast and efficient</a></h3>
<p>The main goal was to provide an SSO solution like Keycloak and others while using a way lower footprint and being more
efficient with resources. For instance, Rauthy can easily run a fully blown SSO provider on just a Raspberry Pi. It
makes extensive use of caching for everything used in the authentication chain to be as fast as possible. Most things
are even cached for several hours and special care has been taken into account in case of cache eviction and
invalidation.</p>
<p>Rauthy comes with two database options:</p>
<ul>
<li>with embedded <a href="https://github.com/sebadob/hiqlite">Hiqlite</a>, which is the default setting</li>
<li>or you can optionally use a Postgres as your database, if you already have an instance running anyway.</li>
</ul>
<p>The resource usage depends a lot on your setup (Hiqlite, Postgres, HA deployment, amount of users, ...), but for a small
set of users, it is usually below 100mb of memory even with the very aggressive, in-memory caching Rauthy uses, and in
some cases even below 50mb.</p>
<h3 id="highly-available"><a class="header" href="#highly-available">Highly Available</a></h3>
<p>Even though it makes extensive use of caching, you can run it in HA mode. <a href="https://github.com/sebadob/hiqlite">Hiqlite</a>
creates its own embedded HA cache and persistence layer. Such a deployment is possible with
both <a href="https://github.com/sebadob/hiqlite">Hiqlite</a> and Postgres.</p>
<h3 id="admin-ui--user-account-dashboard"><a class="header" href="#admin-ui--user-account-dashboard">Admin UI + User Account Dashboard</a></h3>
<p>Rauthy does have an Admin UI which can be used to basically do almost any operation you might need to administrate the
whole application and its users. There is also an account dashboard for each individual user, where users will get a
basic overview over their account and can self-manage som values, password, passkeys, and so on.</p>
<p><img src="https://github.com/sebadob/rauthy/blob/a89a8e9712c567551cb2d25b9da8823e35794f0a/frontend/screenshots/users.png" alt="Admin UI" /></p>
<p><img src="https://github.com/sebadob/rauthy/blob/a89a8e9712c567551cb2d25b9da8823e35794f0a/frontend/screenshots/account.png" alt="Account Dashboard" /></p>
<h3 id="client-branding"><a class="header" href="#client-branding">Client Branding</a></h3>
<p>You have a simple way to create a branding or stylized look for the Login page for each client. The whole color theme
can be changed and each client can have its own custom logo. Additionally, if you modify the branding for the default
<code>rauthy</code> client, it will not only change the look for the Login page, but also for the Account and Admin page.</p>
<p><img src="https://github.com/sebadob/rauthy/blob/c10e9421e65f386718528b15e3d0ace37aff1158/frontend/screenshots/branding.png" alt="Client Branding" /></p>
<h3 id="events-and-auditing"><a class="header" href="#events-and-auditing">Events and Auditing</a></h3>
<p>Rauthy comes with an Event- and Alerting-System. Events are generated in all kinds of scenarios. They can be sent via
E-Mail, Matrix or Slack, depending on the severity and the configured level. You will see them in the Admin UI in
real-time, or you can subscribe to the events stream and externally handle them depending on your own business logic.</p>
<h3 id="brute-force-and-basic-dos-protection"><a class="header" href="#brute-force-and-basic-dos-protection">Brute-Force and basic DoS protection</a></h3>
<p>Rauthy has brute-force and basic DoS protection for the login endpoint. The timeout will be artificially delayed after
enough invalid logins. It auto-blacklists IPs that exceeded too many invalid logins, with automatic expiry of the
blacklisting. You can, if you like, manually blacklist certain IPs as well via the Admin UI.</p>
<h3 id="iot-ready"><a class="header" href="#iot-ready">IoT Ready</a></h3>
<p>With the possibility to run on devices with very limited resources and having compatibility for the OAuth Device
Authorization Grant <code>device_code</code> flow, Rauthy would be a very good choice for IoT projects. The IdP itself can easily
run on a Raspberry Pi and all headless devices can be authenticated via the <code>device_code</code> flow. The <code>rauthy-client</code>
has everything built-in and ready, if you want to use Rust on the IoT devices as well. It has not been checked in a
<code>no_std</code> environment yet, but the client implementation is pretty simple.</p>
<h3 id="scales-to-millions-of-users"><a class="header" href="#scales-to-millions-of-users">Scales to millions of users</a></h3>
<p>Rauthy has no issue handling even millions of users. Everything keeps being fast and responsive, apart from the search
function for users in der Admin UI when you reach the 10+ million users, where searching usually takes ~3 seconds
(depending on your server of course).<br />
The only limiting factor at that point will be your configuration and needs for password hashing security. It really
depends on how many resources you want to use for hashing (more resources == more secure) and how many concurrent logins
at the exact same time you need to support.</p>
<h3 id="features-list"><a class="header" href="#features-list">Features List</a></h3>
<ul>
<li><input disabled="" type="checkbox" checked=""/>
Fully working OIDC provider</li>
<li><input disabled="" type="checkbox" checked=""/>
<a href="https://github.com/sebadob/hiqlite">Hiqlite</a> or Postgres as database</li>
<li><input disabled="" type="checkbox" checked=""/>
Fast and efficient with low footprint</li>
<li><input disabled="" type="checkbox" checked=""/>
Secure default values</li>
<li><input disabled="" type="checkbox" checked=""/>
Highly configurable</li>
<li><input disabled="" type="checkbox" checked=""/>
High-Availability</li>
<li><input disabled="" type="checkbox" checked=""/>
True passwordless accounts with E-Mail + Magic Link + Passkey</li>
<li><input disabled="" type="checkbox" checked=""/>
Dedicated Admin UI</li>
<li><input disabled="" type="checkbox" checked=""/>
Account dashboard UI for each user with self-service</li>
<li><input disabled="" type="checkbox" checked=""/>
OpenID Connect Dynamic Client Registration</li>
<li><input disabled="" type="checkbox" checked=""/>
OpenID Connect RP Initiated Logout</li>
<li><input disabled="" type="checkbox" checked=""/>
OpenID Connect Backchannel Logout</li>
<li><input disabled="" type="checkbox" checked=""/>
OAuth 2.0 Device Authorization Grant flow</li>
<li><input disabled="" type="checkbox" checked=""/>
Upstream Authentication Providers (Login with ...)</li>
<li><input disabled="" type="checkbox" checked=""/>
DPoP tokens for decentralized login flows</li>
<li><input disabled="" type="checkbox" checked=""/>
Ephemeral, dynamic clients for decentralized login flows</li>
<li><input disabled="" type="checkbox" checked=""/>
SCIM v2 for downstream clients</li>
<li><input disabled="" type="checkbox" checked=""/>
All End-User facing sites support i18n server-side translation
with the possibility to add more languages</li>
<li><input disabled="" type="checkbox" checked=""/>
Simple per client branding for the login page</li>
<li><input disabled="" type="checkbox" checked=""/>
Custom roles</li>
<li><input disabled="" type="checkbox" checked=""/>
Custom groups</li>
<li><input disabled="" type="checkbox" checked=""/>
Custom scopes</li>
<li><input disabled="" type="checkbox" checked=""/>
Custom user attributes</li>
<li><input disabled="" type="checkbox" checked=""/>
User attribute binding to custom scopes</li>
<li><input disabled="" type="checkbox" checked=""/>
Configurable password policy</li>
<li><input disabled="" type="checkbox" checked=""/>
Admin API Keys with fine-grained access rights</li>
<li><input disabled="" type="checkbox" checked=""/>
Events and alerting system</li>
<li><input disabled="" type="checkbox" checked=""/>
Optional event persistence</li>
<li><input disabled="" type="checkbox" checked=""/>
Dedicated <code>forward_auth</code> endpoint, in addition to the existing userinfo,
with support for configurable trusted auth headers</li>
<li><input disabled="" type="checkbox" checked=""/>
Optional event notifications via: E-Mail, Matrix, Slack</li>
<li><input disabled="" type="checkbox" checked=""/>
Optional Force MFA for the Admin UI</li>
<li><input disabled="" type="checkbox" checked=""/>
Optional Force MFA for each individual client</li>
<li><input disabled="" type="checkbox" checked=""/>
Additional encryption inside the database for the most critical entries</li>
<li><input disabled="" type="checkbox" checked=""/>
Automatic database backups with configurable retention and auto-cleanup (SQLite only)</li>
<li><input disabled="" type="checkbox" checked=""/>
auto-encrypted backups (<a href="https://github.com/sebadob/hiqlite">Hiqlite</a> only)</li>
<li><input disabled="" type="checkbox" checked=""/>
Ability to push <a href="https://github.com/sebadob/hiqlite">Hiqlite</a> backups to S3 storage</li>
<li><input disabled="" type="checkbox" checked=""/>
auto-restore <a href="https://github.com/sebadob/hiqlite">Hiqlite</a> backups from file or s3</li>
<li><input disabled="" type="checkbox" checked=""/>
Username enumeration prevention</li>
<li><input disabled="" type="checkbox" checked=""/>
Login / Password hashing rate limiting</li>
<li><input disabled="" type="checkbox" checked=""/>
Session client peer IP binding</li>
<li><input disabled="" type="checkbox" checked=""/>
IP blacklisting feature</li>
<li><input disabled="" type="checkbox" checked=""/>
Auto-IP blacklisting for login endpoints</li>
<li><input disabled="" type="checkbox" checked=""/>
Argon2ID with config helper UI utility</li>
<li><input disabled="" type="checkbox" checked=""/>
Housekeeping schedulers and cron jobs</li>
<li><input disabled="" type="checkbox" checked=""/>
JSON Web Key Set (JWKS) autorotation feature</li>
<li><input disabled="" type="checkbox" checked=""/>
Account conversions between traditional password and Passkey only</li>
<li><input disabled="" type="checkbox" checked=""/>
Optional open user registration</li>
<li><input disabled="" type="checkbox" checked=""/>
Optional user registration domain restriction</li>
<li><input disabled="" type="checkbox" checked=""/>
App version update checker</li>
<li><input disabled="" type="checkbox" checked=""/>
SwaggerUI documentation</li>
<li><input disabled="" type="checkbox" checked=""/>
Configurable E-Mail templates for NewPassword + ResetPassword events</li>
<li><input disabled="" type="checkbox" checked=""/>
Prometheus <code>/metrics</code> endpoint on separate port</li>
<li><input disabled="" type="checkbox" checked=""/>
No-Setup migrations between different databases (Yes, even between <a href="https://github.com/sebadob/hiqlite">Hiqlite</a>
and Postgres)</li>
<li><input disabled="" type="checkbox" checked=""/>
Can serve a basic <code>webid</code> document</li>
<li><input disabled="" type="checkbox" checked=""/>
Experimental FedCM support</li>
</ul>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->

                            <a rel="next prefetch" href="getting_started/main.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">

                    <a rel="next prefetch" href="getting_started/main.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
            </nav>

        </div>




        <script>
            window.playground_copyable = true;
        </script>


        <script src="elasticlunr.min.js"></script>
        <script src="mark.min.js"></script>
        <script src="searcher.js"></script>

        <script src="clipboard.min.js"></script>
        <script src="highlight.js"></script>
        <script src="book.js"></script>

        <!-- Custom JS scripts -->


    </div>
    </body>
</html>
